package br.edu.ufcg.ga.parser.args.group;

import java.util.Arrays;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.ParseException;
import org.jgap.Configuration;
import org.jgap.InvalidConfigurationException;

import br.edu.ufcg.ga.CVConfiguration;

public abstract class AbstractMyGroupBuilder implements MyGroupBuilder {

	//XXX Caso mude a implementação do HelpFormatter para lidar direito com os "options" do MyGroupBuilder
	//seria interessante adicionar um "OptionGroup" aqui para armazenar todas as "options" do MyGroupBuilder
	//considerando a primeira "option" como a principal.
	
	public AbstractMyGroupBuilder() {
		init();
	}

	protected abstract void init();

	@Override
	public Option[] getOptions() {
		Option[] otherOptions = getOtherOptions();
		Option[] options = Arrays.copyOf(otherOptions, otherOptions.length+1);
		options[otherOptions.length] = getMainOption();
		return options;
	}

	protected abstract Option getMainOption();

	protected abstract Option[] getOtherOptions();

	public void config(CVConfiguration config, CommandLine commandLine) throws InvalidConfigurationException,
			ParseException {
		if (isMainOptionSelected(commandLine)) {
			ensureHasNeededOptions(commandLine);
			configSafely(config.getConfiguration(), commandLine);
		}
	}

	protected abstract void configSafely(Configuration config, CommandLine commandLine)
			throws InvalidConfigurationException, ParseException;

	protected String getOptionValue(Option option, CommandLine commandLine) {
		String s = commandLine.getOptionValue(option.getOpt());
		if (s == null) {
			s = commandLine.getOptionValue(option.getLongOpt());
		}
		return s;
	}
	
	private boolean hasOption(Option option, CommandLine commandLine){
		return commandLine.hasOption(option.getOpt()) || commandLine.hasOption(option.getLongOpt());
	}

	protected boolean isMainOptionSelected(CommandLine commandLine) {
		return hasOption(getMainOption(), commandLine);
	}

	protected void ensureHasNeededOptions(CommandLine commandLine) throws ParseException {
		for (Option option : getOtherOptions()) {
			String optionValue = getOptionValue(option, commandLine);
			if (optionValue == null) {
				throw new ParseException("ERROR! Missing option <" + option.getOpt() + "> for main option <"
						+ getMainOption().getOpt() + ">");
			}
		}
	}

}
